﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Bettzueche.RLLibrary.Types;

namespace RLProject1.Model {
    /// <summary>
    /// Abstrakte, generische Eligibility-Funktion e(s,a).
    /// <para>
    /// Der Eligibility-Wert (en: Berechtigung, Eignung) gibt an, in welchem Maße ein (ehemaliges)
    /// Zustands-Aktions-Tupel für die aktuelle Belohnung verantwortlich ist. Bei bspw. SarsaLambda
    /// wird dieser Wert zur Aktualisierung der Schätzwerte mit herangezogen und nimmt typischerweise
    /// um so mehr ab, je weiter die Aktion in der Vergangenheit liegt.
    /// </para>
    /// </summary>
    /// <remarks>
    /// Diese abstrakte Funktion wird bisher nicht im Framwork bzw. in der Applikation benutzt.
    /// </remarks>
    /// <typeparam name="S">Type of the state, implementing IState</typeparam>
    /// <typeparam name="A">Type of the action, implementing IAction</typeparam>
    abstract class EligibilityFunction<S, A> : INotifyPropertyChanged
        where S : IState
        where A : IAction
    {
        #region INotifyPropertyChanged Members

        /// <summary>Event, that occurs when a property value changes.</summary>
        public event PropertyChangedEventHandler PropertyChanged;

        void onPropertyChanged(S state, A action) {
            if (PropertyChanged != null) {
                PropertyChangedEventArgs eArg = new SAPropertyChangedEventArgs<S, A>("Eligibility", state, action);
                PropertyChanged(this, eArg);
            }
        }

        #endregion

        #region Properties and Indexer

        /// <summary>
        /// Abstrakter Indexer e[s,a], der den Eligibility-Wert als Double gibt oder setzt.
        /// </summary>
        /// <param name="state">Zustand</param>
        /// <param name="action">AKtion</param>
        /// <returns></returns>
        abstract public double this[S state, A action] { get; set; }

        /// <summary>
        /// Gibt oder setzt den Eligibility.
        /// </summary>
        public object Eligibility { 
            get;
            set;
        }

        #endregion
    }




    /// <summary>
    /// Erweiterung von PropertyChangedEventArgs um State und Action.
    /// </summary>
    /// <typeparam name="S"></typeparam>
    /// <typeparam name="A"></typeparam>
    class SAPropertyChangedEventArgs<S,A> : PropertyChangedEventArgs 
        where S : IState
        where A : IAction
    {
        public S State { get; private set; }
        public A Action { get; private set; }

        public SAPropertyChangedEventArgs(string propertyName, S state, A action) : base(propertyName) {
            State = state;
            Action = action;
        }
    }
}
